package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AuditService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.DeleteMediaRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.atguigu.tingshu.common.constant.SystemConstant.*;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private VodConstantProperties vodConstantProperties;

    @Autowired
    private AuditService auditService;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private RabbitService rabbitService;


    //保存声音信息
    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //将vo对象转成info对象 然后进行比对 有什么使后端复制的属性
        Long albumId = trackInfoVo.getAlbumId();

        //数据库中查询
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (albumInfo == null) {
            throw new GuiguException(500, "专辑不存在");
        }
        //前端传过来的vo对象
        TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
        String textResult = trackInfoVo.getTrackIntro() + trackInfoVo.getTrackTitle() + trackInfoVo.getTrackRichIntro();
        String result = auditService.auditText(textResult);

        //文本通过审核
        if ("pass".equals(result)) {
            //进行音频审核
            //声音是否过审
            String reviewTask = auditService.startReviewTask(trackInfo.getMediaUrl());
            //rabbitService.sendMessage()
            trackInfo.setReviewTaskId(reviewTask);
            trackInfo.setStatus(TRACK_STATUS_ING);
            //设置定时的审核任务 就获取审核的结果 而不是使用rabbitmq的方式进行审核
//            String reviewResult = auditService.getReviewResult(reviewTask);
        } else if ("block".equals(result)) {
            trackInfo.setStatus(TRACK_STATUS_NO_PASS);
        } else if ("review".equals(result)) {
            trackInfo.setStatus(TRACK_STATUS_REVIEWING);
        }


        trackInfo.setUserId(userId);
        trackInfo.setOrderNum(trackInfo.getOrderNum() + 1);
        TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
        //将在腾讯云点播的数据进行返回
        if (trackMediaInfo != null) {
            trackInfo.setMediaType(trackMediaInfo.getType());
            trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
            trackInfo.setMediaSize(trackMediaInfo.getSize());
        }
        //如果前端没有专辑封面则将专辑封面进行复制
        if (trackInfo.getCoverUrl() == null) {
            trackInfo.setCoverUrl(albumInfo.getCoverUrl());
        }
        //设置四个参数
        trackInfoMapper.insert(trackInfo);
        Long trackId = trackInfo.getId();


        //3.保存声音统计数值

        this.saveTrackStat(trackId, TRACK_STAT_PLAY, 0);
        this.saveTrackStat(trackId, TRACK_STAT_COLLECT, 0);
        this.saveTrackStat(trackId, TRACK_STAT_PRAISE, 0);
        this.saveTrackStat(trackId, TRACK_STAT_COMMENT, 0);

        //4.更新专辑信息-声音数量
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        albumInfoMapper.updateById(albumInfo);

    }

    @Override
    public void saveTrackStat(Long trackId, String statType, int statNum) {
        TrackStat trackStat = new TrackStat();
        trackStat.setStatNum(statNum);
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statType);
        trackStatMapper.insert(trackStat);
    }

    @Override
    public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery query) {
        Page<TrackListVo> page = trackInfoMapper.findUserTrackPage(trackListVoPage, query);
        return page;
    }

    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        //更新声音信息
        TrackInfo oldTrackInfo = trackInfoMapper.selectById(id);
        //将前端传的声音转化格式
        TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
        if (!oldTrackInfo.equals(trackInfo)) {
            //获取前端的声音
            TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
            trackInfo.setMediaType(trackMediaInfo.getType());
            trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
            trackInfo.setMediaSize(trackMediaInfo.getSize());
            trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
        }
        this.deleteMedia(oldTrackInfo.getMediaFileId());

        String reviewTask = auditService.startReviewTask(trackInfo.getMediaUrl());
        trackInfo.setReviewTaskId(reviewTask);
        trackInfo.setStatus(TRACK_STATUS_REVIEWING);
        trackInfoMapper.updateById(trackInfo);
    }

    /**
     * 删除音视频文件
     *
     * @param mediaFileId
     */
    @Override
    public void deleteMedia(String mediaFileId) {
        try {
            //1.实例化一个认证对象
            Credential cred = new Credential(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());
            //2.实例化要请求产品的client对象,clientProfile是可选的
            VodClient client = new VodClient(cred, vodConstantProperties.getRegion());
            //3.实例化一个请求对象,每个接口都会对应一个request对象
            DeleteMediaRequest req = new DeleteMediaRequest();
            req.setFileId(mediaFileId);
            //4.返回的resp是一个DeleteMediaResponse的实例，与请求对象对应
            client.DeleteMedia(req);
        } catch (TencentCloudSDKException e) {
            log.error("[专辑服务]删除点播平台文件异常：{}", e);
        }
    }

    /**
     * 删除声音
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeTrackInfo(Long id) {
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        //专辑的id用于后续专辑的更新
        Long albumId = trackInfo.getAlbumId();
        //用于后续的声音列表连续
        Integer orderNum = trackInfo.getOrderNum();
        //删除声音表  声音的id需要是连续的 因此需要删除声音的id 使后面的id-1
        baseMapper.update(null, new LambdaUpdateWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, albumId).gt(TrackInfo::getOrderNum, orderNum).setSql("order_num=order_num-1"));
        //专辑表里面的声音-1
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        albumInfoMapper.updateById(albumInfo);
        //删除云点播上的声音
        //4.删除声音
        trackInfoMapper.deleteById(id);

        //5.删除统计信息
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, id));
        vodService.deleteMedia(trackInfo.getMediaFileId());
    }

    /**
     * 查询声音的列表
     *
     * @param page
     * @param limit
     * @param albumId
     * @param userId
     * @return
     */
    @Override
    public Page<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> trackListVoPage, Long albumId, Long userId) {
        //1.根据专辑的id查询声音列表
        trackListVoPage = albumInfoMapper.findAlbumTrackPage(trackListVoPage, albumId);
        //1.1 在当前的列表中获取声音的id集合
        List<Long> longs = trackListVoPage.getRecords().stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
        //2.根据用户是否登录判断显示付费标识
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //获得免费听书的数量
        Integer tracksForFree = albumInfo.getTracksForFree();
        //付费类型: 0101-免费、0102-vip免费、0103-付费
        String payType = albumInfo.getPayType();
        //2.1未登录
        if (userId == null) {
            //2.1.1 是否为VIP免费 和VIP付费 和免费 获取专辑的付费标识
            if (ALBUM_PAY_TYPE_VIPFREE.equals(payType) || ALBUM_PAY_TYPE_REQUIRE.equals(payType)) {
                trackListVoPage.getRecords().stream().filter(f -> f.getOrderNum() > tracksForFree).forEach(f -> f.setIsShowPaidMark(true));
            }
        } else {
            //3. 登陆 是否是VIP
            Boolean isVip = false;
            //3.0是否为普通用户 用户是否为VIP会员 0:普通用户  1:VIP会员
            UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
            Assert.notNull(userInfoVo, "用户不存在！");
            //3.1 vip 用户 设置用户的vip标识
            if (userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().after(new Date())) {
                isVip = true;
            }


            //3.2专辑是VIP免费的 设置一个可以播放的标识 但是排除专辑或者声音可以购买
            Boolean isNeedCheckBuyStatus = false;
            if (ALBUM_PAY_TYPE_VIPFREE.equals(payType) && !isVip) {
                //显示付费标识
                isNeedCheckBuyStatus = true;
            }

            //3.3专辑是VIP 和普通用户付费的
            if (ALBUM_PAY_TYPE_REQUIRE.equals(payType)) {
                isNeedCheckBuyStatus = true;
            }


            //4.判断是否购买了声音或者专辑
            if (isNeedCheckBuyStatus) {
                //4.1获得本页的声音的id集合
                List<Long> trackIdList = trackListVoPage.getRecords().stream().filter(f -> f.getOrderNum() > tracksForFree).map(m -> m.getTrackId()).collect(Collectors.toList());
                //4.2远程调用用户是否购买了声音或者专辑
                Map<Long, Integer> map = userFeignClient.userIsPaidTrack(userId, albumId, trackIdList).getData();
                //获得声音的是否购买的状态
                map.entrySet().forEach(f -> f.getValue().equals(1));
                trackListVoPage.getRecords().stream().filter(f -> f.getOrderNum() > tracksForFree).forEach(track -> track.setIsShowPaidMark(map.get(track.getTrackId()) == 0));
            }
        }
        //4封装数据进行返回
        return trackListVoPage;
    }

    /**
     * @param trackId
     * @return
     */
    @Override
    public TrackStatVo getTrackStatVo(Long trackId) {
        TrackStatVo trackStatVo = trackInfoMapper.getTrackStatVo(trackId);
        return trackStatVo;
    }

    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
        //1.远程调用用户是否购买声音的数量

        //2.查询声音的列表
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        Long albumId = trackInfo.getAlbumId();
        Integer orderNum = trackInfo.getOrderNum();
        LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, albumId)
                .gt(TrackInfo::getOrderNum, orderNum)
                .select(TrackInfo::getId, TrackInfo::getOrderNum, TrackInfo::getTrackTitle);
        List<TrackInfo> trackInfos = trackInfoMapper.selectList(
                queryWrapper
        );
        HashMap<String, Object> map = new HashMap<>();
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        List<Long> trakIdList = userFeignClient.findUserPaidTrackList(albumId).getData();
        if (trakIdList != null) {
            trackInfos = trackInfos.stream().filter(f -> !trakIdList.contains(f.getId())).collect(Collectors.toList());
        }
        //3.size是没有购买专辑的数量
        int size = trackInfos.size();
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        BigDecimal price = albumInfo.getPrice();

        map.put("name", "本集");
        map.put("price", price);
        map.put("trackCount", 1);
        list.add(map);
        for (int i = 10; i < 50; i += 10) {
            if (size > i) {
                HashMap<String, Object> map1 = new HashMap<>();
                map1.put("name", "后" + i + "集");
                map1.put("price", price.multiply(new BigDecimal(i)));
                map1.put("trackCount", i);
                list.add(map1);
            } else {
                HashMap<String, Object> map2 = new HashMap<>();
                map2.put("name", "全集");
                map2.put("price", price.multiply(new BigDecimal(size)));
                map2.put("trackCount", size);
                list.add(map2);
                break;
            }
        }
        return list;
    }

    /**
     * 获取用户购买的声音
     *
     * @param userId
     * @param trackId
     * @param trackCount
     * @return
     */
    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long userId, Long trackId, Integer trackCount) {


        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        Long albumId = trackInfo.getAlbumId();
        Integer orderNum = trackInfo.getOrderNum();

        LambdaQueryWrapper<TrackInfo> trackInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        trackInfoLambdaQueryWrapper.eq(TrackInfo::getAlbumId, albumId);
        trackInfoLambdaQueryWrapper.ge(TrackInfo::getOrderNum, orderNum);

        List<Long> longList = userFeignClient.findUserPaidTrackList(albumId).getData();
        if (CollUtil.isNotEmpty(longList)) {
            trackInfoLambdaQueryWrapper.notIn(TrackInfo::getId, longList);
        }
        trackInfoLambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum);
        trackInfoLambdaQueryWrapper.last("limit " + trackCount);
        LambdaQueryWrapper<TrackInfo> queryWrapper = trackInfoLambdaQueryWrapper.select(TrackInfo::getId, TrackInfo::getOrderNum, TrackInfo::getTrackTitle, TrackInfo::getAlbumId);
        List<TrackInfo> trackInfos = trackInfoMapper.selectList(queryWrapper);
        return trackInfos;

    }
}
